package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author 请不要叫我高司令
 * @Date 2022/4/13 22:40
 * @Version 1.0
 */

@Service
public class AuditServiceImpl implements IAuditService {


    /**
     * 审核
     *
     * @param wmNews
     */
    @Override
    @Async
    public void audit(WmNews wmNews) {
        System.out.println(Thread.currentThread().getName() + "开始调用自动审核服务");
        if (wmNews.getStatus() == 8 || wmNews.getStatus() == 4) {
            // 判断是否立刻发布文章,判断当前系统时间是否大于等于文章的发布时间
            if (System.currentTimeMillis() <= wmNews.getPublishTime().getTime()) {
                //延迟发布文章
                sendDelayMessage(wmNews);
            } else {
                //调用文章服务保存文章
                saveArticle(wmNews);
            }
        }
        //判断自媒体文章状态，如果为1，进入自动审核状态
        if (wmNews.getStatus() == 1) {
            //获取文章内容的图片和文本
            HashMap map = getTextAndImagesFromContent(wmNews.getContent());
            //提前声明防止空指针
            //文本内容
            String text = (String) map.get("text");
            // 内容图片
            List<String> images = (List<String>) map.get("images");

            //先进行本地敏感词库的一个匹配
            Boolean sensResult = checkSens(wmNews, text);
            if (sensResult != true) {
                return;
            }

            //文本审核，调用阿里云文本审核
            Boolean textResult = checkText(wmNews, text);
            //审核失败返回
            if (textResult != true) {
                return;
            }
            //图片审核，调用阿里云图片审核
            Boolean imageResult = checkImage(wmNews, images);

            if (!imageResult) {
                return;
            }

            // 判断是否立刻发布文章,判断当前系统时间是否大于等于文章的发布时间
            if (System.currentTimeMillis() <= wmNews.getPublishTime().getTime()) {
                //延迟发布文章
                sendDelayMessage(wmNews);
            } else {
                //调用文章服务保存文章
                saveArticle(wmNews);
            }


        }


    }

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 发送延迟消息
     * @param wmNews
     */
    private void sendDelayMessage(WmNews wmNews) {

        // 如果是未到发布时间,修改文章的状态为8 -审核通过待发布
        wmNews.setStatus(8);
        newsService.updateById(wmNews);
        // 发送延迟消息
        RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("article-publish");
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        // 延迟的长度为文章发布时间 - 当前系统时间
        long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
        delayedQueue.offer(wmNews, time, TimeUnit.MILLISECONDS);

    }

    @Autowired
    private IWmSensitiveService sensitiveService;

    /**
     * 本地敏感词过滤
     *
     * @param wmNews
     * @param text
     * @return
     */
    private Boolean checkSens(WmNews wmNews, String text) {

        //初始化DFA算法的map
        if (SensitiveWordUtil.dictionaryMap.size() == 0) {
            //查询本地的敏感词
            LambdaQueryWrapper<WmSensitive> queryWrapper = new LambdaQueryWrapper<>();
            //只查询某一字段。
            queryWrapper.select(WmSensitive::getSensitives);
            List<String> words = sensitiveService.listObjs(queryWrapper, o -> o.toString());
            SensitiveWordUtil.initMap(words);
        }
        //效率低
        //for (String word : words) {
        //    if (wmNews.getLabels().contains(word)) {
        //        return false;
        //    }
        //    if (wmNews.getTitle().contains(word)) {
        //        return false;
        //    }
        //    if (text.contains(word)) {
        //        return false;
        //    }
        //}

        //敏感词比对
        Map<String, Integer> map = SensitiveWordUtil.matchWords(text + wmNews.getTitle() + wmNews.getLabels());
        if (map.size() > 0) {
            wmNews.setStatus(2);
            Set<String> keys = map.keySet();
            String join = String.join("", keys);
            wmNews.setReason("敏感词审核不通过: " + join);
            newsService.updateById(wmNews);
            return false;
        }

        return true;

    }

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private IWmUserService userService;

    @Autowired
    private IWmChannelService channelService;

    /**
     * 远程调用保存文章
     *
     * @param wmNews
     */
    private void saveArticle(WmNews wmNews) {

        // 调用文章服务接口
        // 封装ArticleDto
        ArticleDto dto = new ArticleDto();
        dto.setTitle(wmNews.getTitle());
        // 从 wm_user 查询作者信息
        WmUser wmUser = userService.getById(wmNews.getUserId());
        dto.setAuthorId(wmUser.getApAuthorId());
        dto.setAuthorName(wmUser.getName());
        dto.setChannelId(wmNews.getChannelId());
        // 查询频道名称
        WmChannel wmChannel = channelService.getById(wmNews.getChannelId());
        dto.setChannelName(wmChannel.getName());
        dto.setLayout(wmNews.getType());
        dto.setLabels(wmNews.getLabels());
        dto.setFlag(0);
        // 前端显示的图片是图片地址,中间用逗号分隔
        List<ImageDto> list = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        ArrayList<String> images = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(list)) {
            for (ImageDto imageDto : list) {
                images.add(imageDto.getUrl());
            }
        }
        // 将集合转变成逗号分隔的字符串
        String join = String.join(",", images);
        dto.setImages(join);
        dto.setContent(wmNews.getContent());
        dto.setPublishTime(wmNews.getPublishTime());
        dto.setLabels(wmNews.getLabels());

        ResponseResult<Long> longResponseResult = articleFeign.saveArticle(dto);
        if (longResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {

            Long articleId = longResponseResult.getData();
            if (articleId != null) {
                // 将文章id写回到自媒体文章表中
                wmNews.setArticleId(articleId);
                // 修改文章表的状态为9
                wmNews.setStatus(9);
                newsService.updateById(wmNews);
            }

        }
    }

    @Autowired
    private GreenImageScan imageScan;
    @Autowired
    private MinIOService minIOService;

    /**
     * 阿里云图片审核
     *
     * @param wmNews
     * @param images
     * @return
     */
    private Boolean checkImage(WmNews wmNews, List<String> images) {

        boolean result = false;
        if (images.size() == 0) {
            return true;
        }

        // 有可能封面图片跟内容图片不一样
        //内容里的图片和封面的图片整合
        List<ImageDto> coverImages = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        if (ObjectUtils.isNotEmpty(coverImages)) {
            for (ImageDto coverImage : coverImages) {
                if (!images.contains(coverImage)) {
                    images.add(coverImage.getUrl());
                }
            }
        }

        try {
            // minio服务部署在内网,需要先下载然后去阿里云审核
            ArrayList<byte[]> imageList = new ArrayList<>();
            for (String image : images) {
                if (!StringUtils.isEmpty(image)) {
                    InputStream inputStream = minIOService.download(image);
                    //流转字节数组
                    byte[] bytes = IOUtils.toByteArray(inputStream);
                    imageList.add(bytes);
                }

            }
            //调用阿里云审核
            Map map = imageScan.imageScan(imageList);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    result = true;
                    break;
                case "block":
                    //不通过，状体为2
                    wmNews.setStatus(2);
                    wmNews.setReason("阿里云图片审核失败: " + map.get("label"));
                    newsService.updateById(wmNews);
                    break;
                case "review":
                    //需要人工审核,状态3
                    wmNews.setStatus(3);
                    newsService.updateById(wmNews);
                    break;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;

    }

    @Autowired
    private GreenTextScan textScan;
    @Autowired
    private IWmNewsService newsService;


    /**
     * 阿里云审核文本内容
     *
     * @param wmNews
     * @param text
     * @return
     */
    private Boolean checkText(WmNews wmNews, String text) {

        boolean result = false;
        //全部文本内容拼接:标签+标题+文本内容
        text = text + wmNews.getTitle() + wmNews.getLabels();
        //判断结果
        try {
            Map map = textScan.greenTextScan(text);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    //还没有进行图片审核，不可以设置为通过状态
                    result = true;
                    break;
                case "block":
                    //文章不通过，状体为2
                    wmNews.setStatus(2);
                    wmNews.setReason("阿里云文本审核失败: " + map.get("label"));
                    newsService.updateById(wmNews);
                    break;
                case "review":
                    //需要人工审核,状态3
                    wmNews.setStatus(3);
                    newsService.updateById(wmNews);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;

    }

    /**
     * 获取文章内容中的文本和图片
     *
     * @param content
     * @return
     */
    private HashMap getTextAndImagesFromContent(String content) {

        HashMap<String, Object> map = new HashMap<>();
        StringBuilder sb = new StringBuilder();
        ArrayList<Object> images = new ArrayList<>();

        //String转对象集合
        List<ContentDto> dtos = JSON.parseArray(content, ContentDto.class);
        //遍历集合封装map
        if (ObjectUtils.isNotEmpty(dtos)) {
            for (ContentDto dto : dtos) {

                if (dto.getType().equals("text")) {
                    //添加到文本内容
                    sb.append(dto.getValue());
                } else {
                    //添加到图片集合
                    images.add(dto.getValue());
                }

            }
        }
        map.put("text", sb.toString());
        map.put("images", images);

        return map;

    }
}
